#!/usr/bin/env python
# coding: utf-8

# In[2]:


# 引入必要库
import time
import requests
from bs4 import BeautifulSoup
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
# windows和mac设置中文字体的方式不一样，这里需注意根据实际情况调整
plt.rcParams['font.sans-serif'] = ['SimHei']  #Windows
# plt.rcParams['font.sans-serif'] = ['Songti SC']  #Mac
plt.rcParams['axes.unicode_minus'] = False
get_ipython().run_line_magic('matplotlib', 'inline')
import matplotlib
from pyecharts.charts import Line, Radar
from pyecharts import options as opts


# In[3]:


# 函数默认返回北京市2022年1月到12月的url，可以自行调整
def get_url(city='beijing'):
    '''
    city为城市拼写的字符串，year为年份+月份
    '''
    for time in range(202201,202213):
        url = "http://lishi.tianqi.com/{}/{}.html".format(city,time)
        yield url


# In[4]:


def get_datas(urls = get_url()):
    header = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36"}
    for url in urls:
        while True:
            print(url)
            html = requests.get(url = url, headers = header)
            soup = BeautifulSoup(html.content, 'html.parser')
            date = soup.select("div.tian_three > ul > li > div:nth-of-type(1)")
            max_temp = soup.select("div.tian_three > ul > li > div:nth-of-type(2)")
            min_temp = soup.select("div.tian_three > ul > li > div:nth-of-type(3)")
            weather = soup.select("div.tian_three > ul > li > div:nth-of-type(4)")
            wind_direction = soup.select("div.tian_three > ul > li > div:nth-of-type(5)")
            date = [x.text.split()[0] for x in date]
            max_temp = [x.text[:-1] for x in max_temp[1:]]
            min_temp = [x.text[:-1] for x in min_temp[1:]]
            weather = [x.text for x in weather[1:]]
            wind_direction = [x.text.split()[0] for x in wind_direction[1:]]
            if len(date) > 0:  # 如果抓取到数据就跳出循环，否则再次抓取
                break
        yield pd.DataFrame([date,max_temp,min_temp,weather,wind_direction]).T


# In[5]:


# 获取数据方法
def get_result():
    result = pd.DataFrame()
    for data in get_datas():  
        result = result.append(data)
    return result


# In[6]:


# 执行方法，获取数据
result = get_result()

# 是否存在非空数据
print('空数据有',result.isnull().any().sum())

# 简单查看下爬取到的数据
result.head(5)


# In[7]:


# 改一下列名
result.columns = ["日期","最高温度","最低温度","天气状况","风向"]
# 由于提取的默认是字符串，所以这里更改一下数据类型
result['日期'] = pd.to_datetime(result['日期'])
result["最高温度"] = pd.to_numeric(result['最高温度'])
result["最低温度"] = pd.to_numeric(result['最低温度'])
result["平均温度"] = (result['最高温度'] + result['最低温度'])/2
# 看一下更改后的数据状况
result.info()


# In[8]:


# 温度的分布
sns.distplot(result['平均温度'])


# In[9]:


# 天气状况分布
sns.countplot(result['天气状况'])


# In[10]:


# 按月份统计降雨和没有降雨的天气数量

result['是否降水'] = result['天气状况'].apply(lambda x:'未降水' if x in ['晴','多云','阴','雾','浮尘','霾','扬沙'] else '降水')
rain = result.groupby([result['日期'].apply(lambda x:x.month),'是否降水'])['是否降水'].count()

month = [str(i)+"月份" for i in range(1,13)]
is_rain = [int(rain[i]['降水']) if '降水' in rain[i].index else 0 for i in range(1,13)]
no_rain = [int(rain[i]['未降水']) if '未降水' in rain[i].index else 0  for i in range(1,13)]

line = (Line()
    .add_xaxis(month)
    .add_yaxis('降水天数', is_rain)
    .add_yaxis('未降水天数', no_rain)
    .set_global_opts(title_opts=opts.TitleOpts(title='各月降水天数统计'))
)
line.render_notebook()


# In[11]:


# 按照月份查看最高、最低、平均温度的走势
result.groupby(result['日期'].apply(lambda x:x.month)).mean().plot(kind='line')


# In[12]:


directions = ['北风', '西北风', '西风', '西南风', '南风', '东南风', '东风', '东北风']
schema = []
v = []
days = result['风向'].value_counts()
for d in directions:
    schema.append(opts.RadarIndicatorItem(name=d, max_=100))
    v.append(int(days[d]))
v = [v]
radar=(
    Radar()
    .add_schema(schema)
    .add('风向天数',v)
    .set_global_opts(title_opts=opts.TitleOpts(title='风向统计'))
)
radar.render_notebook()


# In[ ]:





# In[ ]:




